import cgi
import wsgiref.handlers
import os

from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext import db
from prefs import Prefs

class Card(db.Model):
  owner = db.UserProperty()
  card = db.StringProperty(multiline=True)
  contentType = db.StringProperty()
  lastModifiedDate = db.DateTimeProperty(auto_now_add=True)

def getKeyUser(self):
  eMail = self.request.get('eMail')
  if eMail:
    user = users.User(eMail)
    prefsQuery = Prefs.all()
    prefsQuery.filter('owner =', user)
    prefsResults = prefsQuery.fetch(1)
    if (len(prefsResults) != 1):
      self.response.set_status(404, 'No API key set')
    else:
      for prefs in prefsResults:
        if prefs.apiKey == '0':
            return None
        if prefs.apiKey:
          if self.request.get('apiKey') == prefs.apiKey:
            return user

class CardsRoot(webapp.RequestHandler):
  def get(self):
    if self.request.get('fakeMethod'):
      if self.request.get('fakeMethod') == 'delete':
        self.delete()
      elif self.request.get('fakeMethod') == 'head':
        self.head()
      else:
        self.response.set_status(400, 'Invalid HTTP method specified for fakeMethod')
    else:
      if users.get_current_user():
        user = users.get_current_user()
      else:
        user = getKeyUser(self)
      if user:
        query = Card.all()
        query.filter('owner =', user)
        self.response.out.write('[')
        doneFirstLoop = 0
        for result in query:
          if doneFirstLoop:
            self.response.out.write(',"')
          else:
            self.response.out.write('"')
            doneFirstLoop = 1
          self.response.out.write(result.key())
          self.response.out.write('"')
        self.response.out.write(']')
      else:
        self.response.set_status(401, 'You must be logged in to access the cards')

  def put(self):
    self.response.set_status(405, None)

  def post(self):
    if self.request.get('fakeMethod'):
      if self.request.get('fakeMethod') == 'put':
        self.put()
      else:
        self.response.set_status(400, 'Invalid HTTP method specified for fakeMethod')
    else:
      if users.get_current_user():
        user = users.get_current_user()
      else:
        user = getKeyUser(self)
      if user:
        newCard = Card()
        newCard.owner = user
        newCard.card = self.request.body
        newCard.contentType = self.request.headers['Content-Type']
        newCard.put()
        self.response.out.write("<a href=\"/cards/")
        self.response.out.write(newCard.key())
        self.response.out.write("\">/cards/")
        self.response.out.write(newCard.key())
        self.response.out.write("</a>")
      else:
        self.response.set_status(401, 'You must be logged in to access the cards')

  def delete(self):
    self.response.set_status(405, None)

  def head(self):
    if users.get_current_user():
      user = users.get_current_user()
    else:
      user = getKeyUser(self)
    if user:
      query = Card.all()
      query.filter('owner =', user).order('-lastModifiedDate')
      card = query.get()
      if card:
        self.response.headers['Last-Modified'] = card.lastModifiedDate.ctime()
      else:
        self.response.set_status(404, 'No cards found');
    else:
      self.response.set_status(401, 'You must be logged in to access the cards')

class SingleCard(webapp.RequestHandler):
    
  def get(self, id):
    if self.request.get('fakeMethod'):
      if self.request.get('fakeMethod') == 'delete':
        self.delete(id)
      elif self.request.get('fakeMethod') == 'head':
        self.head(id)
      else:
        self.response.set_status(400, 'Invalid HTTP method specified for fakeMethod')
    else:
      card = self.getCard(id)
      if card:
        # For some reason, I can't uncomment the next line or it gives me an error about "Header values must be strings"
        if card.contentType != None:
          self.response.headers['Content-Type'] = card.contentType
        self.response.out.write(card.card)

  def put(self, id):
    card = self.getCard(id)
    if card:
      card.card = self.request.body
      card.contentType = self.request.headers['Content-Type']
      card.lastModifiedDate = datetime.datetime.now()
      card.put()
      self.response.out.write(card.card)

  def post(self, id):
    if self.request.get('fakeMethod'):
      if self.request.get('fakeMethod') == 'put':
        self.put(id)
      else:
        self.response.set_status(400, 'Invalid HTTP method specified for fakeMethod')
    else:
      self.response.set_status(405, None)

  def delete(self, id):
    self.response.out.write('This should delete the card with id=' + id + '. The id will never be used again')

  def head(self, id):
    card = self.getCard(id)
    if card:
      self.response.headers['Last-Modified'] = card.lastModifiedDate.ctime()

  def getCard(self, id):
    if users.get_current_user():
      user = users.get_current_user()
    else:
      user = getKeyUser(self)
    if user:
      card = Card.get(db.Key(id))
      if card:
        if card.owner == user:
          return card
        else:
          self.response.set_status(401, 'You are not the owner of this card')
      else:
        self.response.set_status(404, 'No card exists for that key')
    else:
      self.response.set_status(401, 'You must be logged in')

def main():
  application = webapp.WSGIApplication(
      [
        ('/api/1.0/cards', CardsRoot),
        ('/api/1.0/cards/', CardsRoot),
        ('/api/1.0/cards/(.*)', SingleCard)
      ],
      debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main()
